package cn.edu.gcu.lost.sys.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.security.Key;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.PKCS8EncodedKeySpec;

import javax.crypto.spec.SecretKeySpec;

import com.mysql.fabric.xmlrpc.base.Data;

import net.sf.json.JSONObject;

public class HttpUtils {


    public static String post(String url, String data, String eid) throws Exception {
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);
        String responseBody = null;
        try {

            ResponseHandler<String> responseHandler = new BasicResponseHandler();

            if (!"".equals(eid)) {
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                nvps.add(new BasicNameValuePair("nonce", String.valueOf(System.currentTimeMillis())));
                nvps.add(new BasicNameValuePair("eid", eid));
                nvps.add(new BasicNameValuePair("data", enyte(data, eid)));

                post.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            }

            // System.out.println(url+",eid:"+eid+",msg:"+message+","+nvps.toString());
            responseBody = httpClient.execute(post, responseHandler);
            JSONObject ret = JSONObject.fromObject(responseBody);

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        return responseBody;
    }

    public static String postMethod(String url, String appid, String appSecret) throws Exception {

        HttpPost method = new HttpPost(url);
		/*long timestamp = System.currentTimeMillis()/1000;
		String nonce = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
		float version = 1.0f;
		String authorization = AuthorizationUtil.generateAuthorizationHeader(appid, 
				appSecret, null, timestamp, nonce, version, null, null, null, url, null, "post");*/
        String authorization = appAuth2Treaty(appid, appSecret);
        method.setHeader("authorization", authorization);
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpResponse result = httpClient.execute(method);
        String obj = EntityUtils.toString(result.getEntity());
        return obj;
    }

    //生成authorization请求头
    public static String appAuth2Treaty(String appid, String appSecret) throws Exception {
        String authorization = "OpenAuth2 version=\"%s\", appid=\"%s\", timestamp=%d, nonce=\"%s\", sign=\"%s\"";
        String version = "1.1";
        appid = URLEncoder.encode(appid, "UTF-8");
        long timestamp = System.currentTimeMillis();
        String nonce = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
        String sign = shaHex(version, appid, timestamp + "", nonce, appSecret);
        sign = URLEncoder.encode(sign, "UTF-8");
        authorization = String.format(authorization, version, appid, timestamp, nonce, sign);
        return authorization;
    }

    public static String shaHex(String... data) {
        Arrays.sort(data);
        String join = StringUtils.join(data);
        String sign = DigestUtils.shaHex(join);
        return sign;
    }

    private static String enyte(String data, String eid) {
        try {

            String filePath = HttpUtils.class.getClassLoader().getResource(eid + ".key").getPath();
            // String filePath
            // =System.getProperty("user.dir")+File.separator+eid+".key";

            filePath = filePath.replaceAll("%20", " ");

            byte[] b = FileUtils.readFileToByteArray(new File(filePath));// 找管理员拿key文件，key文件命名为eid.key

            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(b);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey restorePublicKey = kf.generatePrivate(pkcs);
            byte[] bytes = Base64.encodeBase64(encryptLarger(data.getBytes("utf-8"), restorePublicKey));
            String test = new String(bytes, "UTF-8");
            //System.out.print(test);
            return new String(bytes, "UTF-8");
        } catch (FileNotFoundException e) {

            e.printStackTrace();
        } catch (IOException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static byte[] encryptLarger(byte[] data, Key key) throws Exception {
        javax.crypto.Cipher rsa = javax.crypto.Cipher.getInstance("RSA");
        rsa.init(javax.crypto.Cipher.ENCRYPT_MODE, key);

        SecureRandom random = new SecureRandom();
        final byte[] secretKey = new byte[16];
        random.nextBytes(secretKey);

        final javax.crypto.Cipher aes = javax.crypto.Cipher.getInstance("AES");
        SecretKeySpec k = new SecretKeySpec(secretKey, "AES");
        aes.init(javax.crypto.Cipher.ENCRYPT_MODE, k);

        final byte[] ciphedKey = rsa.doFinal(secretKey);
        final byte[] ciphedData = aes.doFinal(data);
        byte[] result = new byte[128 + ciphedData.length];

        System.arraycopy(ciphedKey, 0, result, 0, 128);
        System.arraycopy(ciphedData, 0, result, 128, ciphedData.length);
        return result;
    }

    private static String getRSAPrivateKeyAsNetFormat(byte[] encodedPrivateKey) {
        try {
            StringBuffer buff = new StringBuffer(1024);

            PKCS8EncodedKeySpec pvkKeySpec = new PKCS8EncodedKeySpec(
                    encodedPrivateKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPrivateCrtKey pvkKey = (RSAPrivateCrtKey) keyFactory
                    .generatePrivate(pvkKeySpec);

            buff.append("<RSAKeyValue>");
            buff.append("<Modulus>"
                    + encodeBase64(removeMSZero(pvkKey.getModulus()
                    .toByteArray())) + "</Modulus>");

            buff.append("<Exponent>"
                    + encodeBase64(removeMSZero(pvkKey.getPublicExponent()
                    .toByteArray())) + "</Exponent>");

            buff.append("<P>"
                    + encodeBase64(removeMSZero(pvkKey.getPrimeP()
                    .toByteArray())) + "</P>");

            buff.append("<Q>"
                    + encodeBase64(removeMSZero(pvkKey.getPrimeQ()
                    .toByteArray())) + "</Q>");

            buff.append("<DP>"
                    + encodeBase64(removeMSZero(pvkKey.getPrimeExponentP()
                    .toByteArray())) + "</DP>");

            buff.append("<DQ>"
                    + encodeBase64(removeMSZero(pvkKey.getPrimeExponentQ()
                    .toByteArray())) + "</DQ>");

            buff.append("<InverseQ>"
                    + encodeBase64(removeMSZero(pvkKey.getCrtCoefficient()
                    .toByteArray())) + "</InverseQ>");

            buff.append("<D>"
                    + encodeBase64(removeMSZero(pvkKey.getPrivateExponent()
                    .toByteArray())) + "</D>");
            buff.append("</RSAKeyValue>");
            System.out.println(buff.toString());
            return buff.toString();
        } catch (Exception e) {
            System.err.println(e);
            return null;
        }
    }

    private static byte[] removeMSZero(byte[] data) {
        byte[] data1;
        int len = data.length;
        if (data[0] == 0) {
            data1 = new byte[data.length - 1];
            System.arraycopy(data, 1, data1, 0, len - 1);
        } else {
            data1 = data;
        }
        return data1;
    }

    /**
     *  
     *      * base64编码 
     *      * @param input 
     *      * @return 
     *      * @throws Exception 
     *      
     */
    public static String encodeBase64(byte[] input) throws Exception {
        Class clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
        Method mainMethod = clazz.getMethod("encode", byte[].class);
        mainMethod.setAccessible(true);
        Object retObj = mainMethod.invoke(null, new Object[]{input});
        return (String) retObj;
    }
	    
	/*public static void main(String[] args) {
		String filePath = HttpUtils.class.getClassLoader().getResource("101"+ ".key").getPath();
		// String filePath
		// =System.getProperty("user.dir")+File.separator+eid+".key";

		filePath = filePath.replaceAll("%20", " ");
		filePath = "E:\\华广私有云培训项目\\scut\\src\\main\\resources\\101.key";
		byte[] b;
		try {
			b = FileUtils.readFileToByteArray(new File(filePath));
			HttpUtils.getRSAPrivateKeyAsNetFormat(b);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}// 找管理员拿key文件，key文件命名为eid.key

	}*/

}
